home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 9 / The PC-SIG Library on CD ROM - Ninth Edition.iso / 001_100 / DISK0041 / DISK0041.ZIP / MSYIBM.ASM < prev    next >
Assembly Source File  |  1984-12-08  |  31KB  |  1,181 lines

  1.  
  2.     title term
  3.  
  4. ; edit history
  5. ; Fixed destructive tab problem (received from many people)
  6. ; Fixed insert/delete line problem when at bottom/top of screen.
  7. ; Newlines never scroll in inverse video lines
  8. ; Implemented cursor save/restore (from Univ. Md.)
  9. ; "Echo" status on mode corrected.
  10. ; JD, 6 December 1984
  11.  
  12.     public    term, gss        ; entry points
  13.     include    msdefs.h
  14.  
  15. ; some character definitions
  16.  
  17. chesc    equ    27
  18. bel    equ    7
  19.  
  20. print_out equ    05h            ; dos function to print to printer
  21. pbout    equ    02h            ; dos function to print a character
  22. prscan    equ    72h            ; print-screen scan code...
  23. upscan    equ    49h            ; up page
  24. dnscan    equ    51h            ; down page
  25. ctlup    equ    84h            ; ctl-up page
  26. ctldn    equ    76h            ; ctl-down page
  27. homscn    equ    47h            ; home screen
  28. endscn    equ    4fh            ; end of screen
  29. screen    equ    10h            ; bios screen call
  30. kb    equ    16h            ; keyboard interrupt
  31. alt_shift equ    8H            ; alt shift key down
  32. ctl_shift equ    4H            ; ctl key down
  33. left_shift equ    2H            ; left shift key down
  34. right_shift equ    1H            ; right shift key down
  35.  
  36. timer    equ    40h            ; timer port
  37. bel_prt    equ    61h            ; speaker control
  38.  
  39. crt_status equ    3dah            ; crt status port
  40. disp_enb   equ    8            ; display enable bit
  41.  
  42. uparr    equ    48h            ; scan codes for arrow keys
  43. dnarr    equ    50h
  44. lftarr    equ    4bh
  45. rgtarr    equ    4dh
  46.  
  47.  
  48. modfrm    struc                ; format of mode line
  49.     db    'Esc chr: '
  50. m_echr    db    2 dup (?)
  51.     db    ', Port: '
  52. m_prt    db    1 dup (?)
  53.     db    ', Speed: '
  54. m_baud    db    4 dup (?)
  55.     db    ', Parity: '
  56. m_par    db    4 dup (?)
  57.     db    ', Echo: '
  58. m_echo    db    3 dup (?)
  59.     db    ', Type '
  60. m_hlp    db    2 dup (?)
  61.     db    '? for Help'
  62. modfrm    ends
  63.  
  64. datas    segment    public 'datas'
  65. waste    db    100h dup (?)        ;*** need this junk because assembler
  66.                     ;*** generates non-relocatable offsets
  67.                     ;*** for things like 
  68.                     ;*** "sub di,offset foo"
  69.                     ;*** if offset foo < 100H
  70. ; stuff for screen routines
  71. flags    db    ?            ; status flags...
  72. flags1    db    0            ; internal flags.
  73. prtscr    equ    80h            ; print screen pressed
  74. lnwrap    equ    40h            ; line wrap enabled.
  75. inited    equ    08h            ; been here before...
  76. cursor    dw    ?
  77. esc_ch    db    ?
  78. argadr    dw    ?            ; address of arg blk
  79. ckeys    db    0,prscan,dnscan,upscan,endscn,homscn,ctlup,ctldn
  80.     db    uparr,dnarr,lftarr,rgtarr
  81. lckeys    equ    $-ckeys
  82. ; ckacts must parallel ckeys above...
  83. ckacts    dw    trnbrk,trnprs,upwpg,dnwpg,endwnd,homwnd,dnwind,upwind
  84.     dw    trnupw,trndnw,trnlfw,trnrgw
  85.  
  86. uptrn    db    esc,'A'
  87. dntrn    db    esc,'B'
  88. rgtrn    db    esc,'C'
  89. lftrn    db    esc,'D'
  90.  
  91. spctab    db    chesc,cr,lf,bs,tab,bel
  92. lspctab    equ    $-spctab
  93. spcjmp    dw    outesc,outcr,outlf,outbs,outtab,outbel    ; must match spctab
  94. esctab    db    'YABCDEFGHIJKLM'
  95.     db    'NOZ@[pq<vw'
  96.     db    'jk'
  97. lesctab    equ    $-esctab
  98. ; escjmp must parallel esctab above
  99. escjmp    dw    movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
  100.     dw    revind,clreow,clreol,inslin,dellin,delchr,noins
  101.     dw    vtident,entins,doansi
  102.     dw    invvid,nrmvid,outign,dowrap,nowrap
  103.     dw    savecur,restcur
  104. vtidstr    db    chesc,'/K'
  105. lvtidst    equ    $-vtidstr
  106. coord    dw    ?
  107. insmod    db    ?
  108. wcoord    dw    ?
  109. ttstate    dw    outtt0
  110. curattr    db    ?            ; current attribute
  111. ansarg    db    ?            ; ansi argument value
  112. igncnt    db    ?            ; # of chars to ignore
  113. beldiv    dw    2dch            ; 550 hz?
  114. crt_mode db    ?
  115. crt_cols db    ?
  116. crt_lins db    ?    
  117. low_rgt    dw    ?            ; lower right corner of window
  118. ; key redefinitions
  119. ktrntab    dw    ?            ; address of translation table
  120. krpltab    dw    ?            ; address of replacement table
  121. tmptab    db    0eh,3bh            ; scan code for bs, f1
  122. ktlen    dw    ?
  123. modbuf    modfrm    <>            ; mode line buffer
  124. ; routine to call for captured output
  125. captrtn    dw    ?
  126. oldcur    dw    0            ; save'd cursor position
  127. ; some static data for mode line
  128. unkbaud    db    'Unk '            ; must be 4 chars...
  129. baudn    db    '45.5'
  130.     db    '  50'
  131.     db    '  75'
  132.     db    ' 110'
  133.     db    ' 135'
  134.     db    ' 150'
  135.     db    ' 300'
  136.     db    ' 600'
  137.     db    '1200'
  138.     db    '1800'
  139.     db    '2000'
  140.     db    '2400'
  141.     db    '4800'
  142.     db    '9600'
  143. baudnsiz  equ    14            ; # of baud rates known (tbl size / 4)
  144. parnams    db    'Even'
  145.     db    'Mark'
  146.     db    'None'
  147.     db    'Odd '            ; must be 4 chars
  148.     db    'Spc '
  149. offmsg    db    'Off'
  150. onmsg    db    'On '
  151. lclmsg    db    'Lcl'
  152. remmsg    db    'Rem'
  153. ; storage for multi-window stuff
  154. swidth    equ    80
  155. slen    equ    24
  156. npgs    equ    5            ; # of pages on each side
  157. bsize    equ    swidth*slen*npgs*2
  158. scrsav    dw    swidth*slen dup (0700H)    ; a blank screen
  159.  
  160. ; circular buffer.  To work properly, the buffer size should be an exact
  161. ; multiple of swidth*2
  162. cbuf    struc
  163. pp    dw    ?            ; place ptr in buffer
  164. bend    dw    ?            ; end of buffer
  165. orig    dw    ?            ; buffer origin
  166. lcnt    dw    0            ; # of lines in buffer.
  167. cbuf    ends
  168.  
  169. topbuf    db    bsize dup (?)
  170. botbuf    db    bsize dup (?)        ; top and bottom windows
  171. tlbuf    db    swidth*2 dup (?)
  172. blbuf    db    swidth*2 dup (?)
  173. twnd    cbuf    <topbuf,topbuf+bsize-1,topbuf,0>
  174. bwnd    cbuf    <botbuf,botbuf+bsize-1,botbuf,0>
  175. portno    db    ?
  176. prton    db    'Printer: on'
  177. prtnlen    equ    $-prton
  178. prtoff    db    'Printer: off'
  179. prtflen    equ    $-prtoff
  180. datas    ends
  181.  
  182. code    segment    public            ; code segment
  183.     extrn    prtchr:near,outchr:near,sendbr:near
  184.     assume    cs:code,ds:datas,es:datas
  185.  
  186. scrini    proc    near            ; init screen stuff
  187.     mov    ah,15            ; read video state...
  188.     int    screen
  189.     mov    crt_mode,al        ; save crt mode
  190.     cmp    ah,crt_cols        ; is real # of cols < passed?
  191.     jge    scrin1            ; no
  192.     mov    crt_cols,ah        ; yes, save # of cols
  193. scrin1:    mov    dl,crt_cols        ; # of cols again
  194.     mov    dh,crt_lins        ; and # of rows
  195.     dec    dl
  196.     dec    dh
  197.     mov    low_rgt,dx        ; save away window address
  198.     mov    insmod,0        ; not in insert mode
  199.     mov    dx,cursor        ; assume old cursor
  200.     test    flags1,inited        ; have we been here before?
  201.     jnz    scrin4            ; yes, use old cursor
  202.     mov    curattr,07        ; else set nice screen attribute
  203.     mov    ttstate,offset outtt0    ; normal screen state
  204.     mov    ah,3            ; figure out where cursor is
  205.     xor    bh,bh            ; page 0
  206.     int    screen            ; read cursor position
  207.     cmp    dh,crt_lins        ; past logical end of screen?
  208.     jb    scrin2            ; no, keep going
  209.     mov    dh,byte ptr low_rgt+1    ; yes, just use lower right corner
  210. scrin2:    cmp    dl,crt_cols        ; maybe past right margin
  211.     jb    scrin3            ; no, use the way it is
  212.     mov    dl,byte ptr low_rgt
  213. scrin3:    mov    cursor,dx        ; init cursor
  214. scrin4:    mov    ah,2
  215.     xor    bh,bh
  216.     int    screen            ; set cursor in case it moved
  217.     ret
  218. scrini    endp
  219.  
  220. argini    proc    near            ; read passed arguments
  221.     mov    bx,argadr        ; base of argument block
  222.     mov    al,[bx].flgs        ; get flags
  223.     and    al,capt+emheath+havtt+trnctl+lclecho+modoff
  224.     mov    flags,al        ; mask for allowable and save
  225.     and    flags1,not (prtscr)    ; these are allowable
  226.                     ; (others remain).
  227.     mov    al,[bx].prt
  228.     cmp    al,portno        ; using same port?
  229.     je    argin1            ; yes, go on
  230.     and    flags1,not inited    ; else re-init stuff
  231. argin1:    mov    portno,al        ; update port number
  232.     mov    al,[bx].cols
  233.     mov    crt_cols,al
  234.     mov    al,[bx].rows
  235.     mov    crt_lins,al        ; init # of rows and cols
  236.     mov    ax,[bx].captr
  237.     mov    captrtn,ax        ; buffer capture routine
  238.     mov    ax,[bx].belld
  239.     mov    beldiv,ax        ; bell divisor
  240.     mov    ax,[bx].klen
  241.     mov    ktlen,ax        ; length of key redef tbl
  242.     mov    ax,[bx].ktab
  243.     mov    ktrntab,ax        ; save key translation table
  244.     mov    ax,[bx].krpl
  245.     mov    krpltab,ax
  246.     mov    al,[bx].escc
  247.     mov    esc_ch,al
  248.     ret                ; that's it
  249. argini    endp
  250.  
  251. modlin    proc    near            ; turn on mode line
  252.     mov    al,esc_ch
  253.     mov    modbuf.m_echr,' '    ; first char is initial space
  254.     mov    modbuf.m_hlp,' '    ; goes here too.
  255.     cmp    al,32            ; printable?
  256.     jnb    modl1            ; yes, keep going
  257.     add    al,40h            ; made printable
  258.     mov    modbuf.m_echr,'^'    ; note control char
  259.     mov    modbuf.m_hlp,'^'
  260. modl1:    mov    modbuf.m_echr+1,al    ; fill in character
  261.     mov    modbuf.m_hlp+1,al
  262.     mov    bx,argadr        ; get argument block
  263.     mov    al,[bx].baudb        ; get baud bits
  264.     mov    si,offset unkbaud    ; assume unknown baud
  265.     cmp    al,baudnsiz        ; too big?
  266.     jnb    modl2            ; yes, use default
  267.     mov    cl,2            ; each is 4 bytes long
  268.     shl    al,cl
  269.     mov    ah,0
  270.     add    ax,offset baudn
  271.     mov    si,ax
  272. modl2:    mov    cx,size m_baud        ; length of baud space
  273.     mov    di,offset modbuf.m_baud
  274.     rep    movsb            ; copy in baud rate
  275.     mov    al,[bx].parity        ; get parity code
  276.     mov    cl,2            ; each is 4 bytes long...
  277.     shl    al,cl
  278.     mov    ah,0
  279.     add    ax,offset parnams    ; names of parity settings
  280.     mov    si,ax
  281.     mov    cx,4            ; each is 4 long
  282.     mov    di,offset modbuf.m_par
  283.     rep    movsb
  284.     mov    si,offset remmsg    ; Assume remote echoing.
  285.     test    flags,lclecho        ; Is remote side echoing?
  286.     jz    modl4            ; Yes, keep going
  287.     mov    si,offset lclmsg    ; Else it's local echoing. 
  288. modl4:    mov    cx,3            ; size of on/off
  289.     mov    di,offset modbuf.m_echo
  290.     rep    movsb
  291.     mov    al,'1'
  292.     cmp    portno,1        ; port 1?
  293.     je    modl5            ; yes, keep going
  294.     mov    al,'2'
  295. modl5:    mov    modbuf.m_prt,al        ; fill in port number
  296.     mov    cx,size modfrm        ; this is size of mode line
  297.     mov    si,offset modbuf    ; mode line image
  298. ; alternate entry to write an alternate mode line
  299. modwrt:    push    cx
  300.     push    si            ; save mode line and size
  301.     mov    dx,24 * 100h        ; 25th line for mode line
  302.     push    word ptr curattr    ; save current attributes
  303.     mov    curattr,70h        ; want inverse video
  304.     call    clreol            ; clear to end of line...
  305.     pop    word ptr curattr    ; restore attributes
  306.     mov    dx,24 * 100h
  307.     mov    bh,0
  308.     mov    ah,2            ; set cursor position
  309.     int    screen
  310.     pop    si
  311.     pop    cx            ; restore these
  312. modl6:    lodsb                ; get a byte
  313.     mov    ah,14            ; write to terminal
  314.     mov    bh,0            ; page 0
  315.     int    screen
  316.     loop    modl6            ; write out entire mode line
  317.     mov    dx,cursor
  318.     mov    ah,2
  319.     mov    bh,0
  320.     int    screen            ; put cursor back where it belongs
  321.     ret                ; and return
  322. modlin    endp
  323.  
  324. clrmod    proc    near            ; clear mode line
  325.     mov    ax,600h            ; blank window
  326.     mov    cx,24 * 100h        ; beginning of window
  327.     mov    dx,24 * 100h + 79    ; end of window
  328.     mov    bh,07            ; nice attribute
  329.     int    screen            ; clear mode line
  330.     ret                ; and return
  331. clrmod    endp
  332.  
  333. term    proc    near            ; terminal emulator entry point
  334.  
  335.     mov    argadr,ax        ; save argument ptr
  336.     push    es            ; save caller's extra segment address
  337.     mov    ax,seg datas
  338.     mov    es,ax
  339.  
  340.     call    argini            ; init options from arg address
  341.  
  342.     call    scrini            ; init screen stuff
  343.  
  344.     test    flags1,inited        ; have we run yet?
  345.     jz    term1            ; no, forget this part
  346.     call    restscr            ; restore screen
  347. term1:    or    flags1,inited        ; remember we've run already.
  348.  
  349.     call    clrmod            ; empty mode line
  350.     test    flags,modoff        ; is mode line disabled?
  351.     jnz    lp            ; yes, skip it
  352.     call    modlin            ; turn on mode line
  353.  
  354. lp:    call    portchr            ; char at port?
  355.      jnc    chkinp            ; no, keep going
  356.     call    outtty            ; print on terminal
  357.  
  358. chkinp:    mov    ah,1
  359.     int    kb
  360.     jz    lp            ; nothing available...
  361.     xor    ah,ah
  362.     int    kb            ; get the char from the buffer
  363.     push    ax            ; save character temporarily
  364.     call    gss            ; get shift state into al
  365.     mov    bl,al            ; save shift state
  366.     pop    ax
  367.  
  368.     cmp    al,esc_ch        ; escape character?
  369.     je    quit            ; yes, stop here
  370.  
  371.     call    trnout            ; translate if nec., output to prt
  372.     jmp    chkinp            ; and keep going
  373.  
  374. quit:    call    clrmod            ; erase mode line
  375.     call    savescr            ; save screen
  376.  
  377.     mov    al,flags
  378.     mov    bx,argadr
  379.     mov    [bx].flgs,al        ; update flags in arg block
  380.     pop    es            ; restore segment register
  381.     ret                ; and return to caller
  382.  
  383. term    endp
  384.  
  385. ; get shift state into al.  We only care about shift, ctl, and alt keys.
  386. ; right shift is collapsed into left shift.
  387. gss    proc    near
  388.     mov    ah,2
  389.     int    kb            ; get current shift state
  390.     mov    bl,al            ; copy for a moment
  391.     and    bl,right_shift        ; mask out all but right shift
  392.     shl    bl,1            ; move right shift to left shift pos
  393.     or    al,bl            ; collapse shift bits
  394.     and    al,(left_shift + alt_shift + ctl_shift)
  395.     ret
  396. gss    endp
  397.  
  398. ; save the screen so we can restore it
  399. ; maybe save cursor also.
  400. savescr    proc    near
  401.     push    ds
  402.     mov    si,0
  403.     mov    di,offset scrsav    ; place to put screen
  404.     mov    cx,80*24        ; # of words on screen
  405.     call    scrseg
  406.     push    ax            ; save screen segment
  407.     call    scrwait            ; wait for screen to be ready
  408.     pop    ds            ; address screen
  409.     rep    movsw            ; save the screen
  410.     pop    ds            ; restore this
  411.     ret                ; and return
  412. savescr    endp
  413.  
  414. ; restore screen from scrsav buffer
  415. restscr    proc    near
  416.     push    es
  417.     mov    si,offset scrsav    ; source
  418.     mov    di,0
  419.     mov    cx,80*24
  420.     call    scrseg
  421.     mov    es,ax
  422.     call    scrwait
  423.     rep    movsw            ; restore it
  424.     pop    es
  425.     ret
  426. restscr    endp
  427.  
  428. ; send the character in al out to the serial port
  429. ; handle echoing also...
  430. outprt    proc    near
  431.     test    flags,lclecho        ; echoing?
  432.     jz    outpr1            ; no, forget it
  433.     push    ax            ; save char
  434.     call    outtty            ; print it
  435.     pop    ax            ; restore
  436. outpr1:    mov    ah,al            ; this is where outchr expects it
  437.     call    outchr            ; output to the port
  438.      nop
  439.      nop
  440.      nop                ; skip returns...
  441.     ret
  442. outprt    endp
  443.  
  444. ; returns with carry on if a character is available
  445.  
  446. portchr    proc    near
  447.     call    prtchr            ; character at port?
  448.      jmp    short portc1        ; yes, go handle
  449.     nop                ; skip return is stupid...
  450.     clc                ; no carry -> no character
  451.     ret                ; and return...
  452. portc1:    and    al,7fh            ; we don't worry about parity here
  453.     stc                ; have a character
  454.     ret                ; and return
  455. portchr    endp
  456.  
  457.  
  458. ; translate the scan code in ah according to the translate table
  459. ; given in ktrntab/krpltab, output to port.  If no translation,
  460. ; use ascii char in al. (should probably include shift state
  461. ; somewhere).  Shift state is in bl.
  462. trnout    proc    near
  463.     test    flags,havtt        ; translate table given?
  464.     jz    trnou3            ; no, just output character
  465.     push    ax            ; save original value
  466.     mov    al,ah            ; put scan code into ah
  467.     mov    ah,bl            ; shift state into top half.
  468.     mov    di,ktrntab        ; pick up translate tbl
  469.     mov    cx,ktlen        ; length of tbl
  470.     repne    scasw            ; look for our key
  471.     pop    ax            ; recover character
  472.     jne    trnou3            ; not found, forget it
  473.     sub    di,ktrntab        ; get index into tbl
  474.     sub    di,2            ; (minus 2 for pre-increment)
  475.     mov    bx,krpltab        ; get replacement table
  476.     mov    si,[bx][di]        ; and addr of replacement
  477.     mov    cl,[si]            ; get first byte (length)
  478.     xor    ch,ch            ; clear high-order byte
  479.     inc    si            ; point to translation string
  480. trnou2:    lodsb                ; get a byte
  481.     push    si
  482.     push    cx            ; save important registers
  483.     call    outprt            ; send to port
  484.     pop    cx
  485.     pop    si
  486.     loop    trnou2            ; send all chars
  487.     ret                ; and return
  488. trnou3:    cmp    ah,4eh            ;*** plus key thing?
  489.     je    trnmod            ; yes, go toggle mode line
  490.     cmp    al,0            ; is it a special code?
  491.     jne    trnou4            ; no, don't do this
  492.     mov    al,ah            ; get scan code
  493.     mov    cx,lckeys        ; length of table
  494.     mov    di,offset ckeys        ; table address
  495.     repne    scasb
  496.     mov    al,0            ; ascii code was 0...
  497.     jne    trnou4            ; not found, keep going
  498.     sub    di,offset ckeys+1    ; get table offset
  499.     shl    di,1            ; shift for word offset
  500.     jmp    ckacts[di]        ; jump to appropriate routine
  501. trnou4:    call    outprt            ; just output single char
  502.     ret                ; and return
  503.  
  504. trnmod:    test    flags,modoff        ; mode line already off?
  505.     jnz    trnm1            ; yes, go turn on
  506.     call    clrmod            ; no, clear mode line here
  507.     or    flags,modoff        ; turn on flag
  508.     ret                ; and return
  509. trnm1:    call    modlin            ; turn on mode line
  510.     and    flags,not modoff    ; clear flag
  511.     ret                ; and return
  512.  
  513. trnbrk:    mov    ah,dconio
  514.     mov    dl,0ffH
  515.     int    dos            ; read the bogus ^C DOS gets.
  516.     call    sendbr
  517.     ret
  518. trnprs:    xor    flags1,prtscr        ; flip the flag
  519.     and    flags,not modoff    ; turn on mode line
  520.     mov    si,offset prton
  521.     mov    cx,prtnlen
  522.     test    flags1,prtscr        ; did it go on?
  523.     jnz    trnpr1            ; yes, say so
  524.     mov    si,offset prtoff
  525.     mov    cx,prtflen
  526. trnpr1:    call    modwrt            ; write into mode line
  527.     ret                ; and return
  528.  
  529. ; common entry for arrow keys
  530. trnarr:    mov    cx,2            ; length is always 2
  531.     jmp    trnou2            ; go send definition
  532.  
  533. trnupw:    mov    si,offset uptrn
  534.     jmp    trnarr
  535.  
  536. trndnw:    mov    si,offset dntrn
  537.     jmp    trnarr
  538.  
  539. trnlfw:    mov    si,offset lftrn
  540.     jmp    trnarr
  541.  
  542. trnrgw:    mov    si,offset rgtrn
  543.     jmp    trnarr
  544.  
  545. trnout    endp
  546.  
  547. ; move viewing window up (screen moves down).
  548. ; alternate entry upwin2 doesn't beep if invalid.
  549. upwind    proc    near
  550.     mov    ax,offset tlbuf    ; place to put line temporarily
  551.     mov    bx,offset twnd ; where to get lines from
  552.     call    getcirc        ; try to get a line
  553.     jnc    upwin3        ; have a line, go show it
  554.     call    outbel        ; else ring bel
  555.     ret            ; and return
  556. upwin2:    mov    ax,offset tlbuf
  557.     mov    bx,offset twnd
  558.     call    getcirc
  559.     jnc    upwin3
  560.     ret            ; this just rets if no line avail.
  561. upwin3:    mov    ax,offset blbuf    ; place for bottom line
  562.     call    getbot        ; fetch bottom line
  563.     mov    ax,offset blbuf
  564.     mov    bx,offset bwnd
  565.     call    putcirc        ; save in circular buffer
  566.     mov    ax,701h        ; scroll down one line
  567.     xor    cx,cx        ; from top
  568.     mov    dx,low_rgt    ; to bottom
  569.     mov    bh,curattr
  570.     int    screen        ; scroll it down
  571.     mov    di,0        ; offset for destination
  572.     mov    si,offset tlbuf    ; where to get line from
  573.     mov    cx,swidth    ; length of line
  574.     push    es
  575.     call    scrseg
  576.     push    ax
  577.     call    scrwait
  578.     pop    es
  579.     rep    movsw        ; copy the line in
  580.     pop    es        ; restore this
  581.     ret            ; and return
  582. upwind    endp
  583.  
  584.  
  585. ; move viewing window down a line (screen scrolls up)
  586. ; entry dwin2 does same w/out checking to see if scroll is legal
  587. dnwind    proc    near
  588.     mov    ax,offset blbuf    ; place to put line temporarily
  589.     mov    bx,offset bwnd ; where to get lines from
  590.     call    getcirc        ; try to get a line
  591.     jnc    dnwin3        ; have a line, go show it
  592.     call    outbel        ; else ring bel
  593.     ret            ; and return
  594. dnwin2:    mov    ax,offset blbuf
  595.     mov    bx,offset bwnd
  596.     call    getcirc
  597.     jnc    dnwin3
  598.     ret            ; this just rets if no line avail.
  599. dnwin3:    call    scrprep        ; save top line
  600.     mov    ax,601h        ; scroll up one line
  601.     xor    cx,cx        ; from top
  602.     mov    dx,low_rgt    ; to bottom
  603.     mov    bh,curattr
  604.     int    screen        ; scroll it down
  605.     mov    dx,low_rgt
  606.     mov    dl,0        ; get addr of last line
  607.     call    scrloc
  608.     mov    di,ax        ; this is offset in dest
  609.     mov    si,offset blbuf    ; where to get line from
  610.     mov    cx,swidth    ; length of line
  611.     push    es
  612.     call    scrseg
  613.     push    ax
  614.     call    scrwait
  615.     pop    es
  616.     rep    movsw        ; copy the line in
  617.     pop    es        ; restore this
  618.     ret            ; and return
  619. dnwind    endp
  620.  
  621. ; move viewing window down as much as possible...
  622. endwnd    proc    near
  623.     mov    cx,1000            ; large number of lines
  624.     jmp    dnwp1            ; and enter dwnpg
  625. endwnd    endp
  626.  
  627. ; scroll viewing window down (contents move up) crt_lins times...
  628. dnwpg    proc    near
  629.     mov    cl,crt_lins
  630.     mov    ch,0
  631. dnwp1:    push    cx            ; save this
  632.     call    dnwin2
  633.     pop    cx
  634.     loop    dnwp1
  635.     ret                ; and return
  636. dnwpg    endp
  637.  
  638. ; home viewing window
  639. homwnd    proc    near
  640.     mov    cx,1000            ; large # of lines
  641.     jmp    upwp1            ; join upwpg
  642. homwnd    endp
  643.  
  644. ; scroll viewing window up (screen moves down) a page
  645. upwpg    proc    near
  646.     mov    cl,crt_lins
  647.     mov    ch,0
  648. upwp1:    push    cx
  649.     call    upwin2
  650.     pop    cx
  651.     loop    upwp1
  652.     ret                ; and return
  653. upwpg    endp
  654.  
  655. ; get the bottom line into the buffer pointed to by ax.
  656. getbot    proc    near
  657.     push    ds
  658.     mov    di,ax            ; save dest
  659.     mov    cx,swidth
  660.     mov    dx,low_rgt
  661.     mov    dl,0
  662.     call    scrloc
  663.     mov    si,ax
  664.     call    scrseg
  665.     push    ax
  666.     call    scrwait
  667.     pop    ds
  668.     rep    movsw
  669.     pop    ds
  670.     ret
  671. getbot    endp
  672.  
  673. ; put a line into the circular buffer.  Pass the buffer structure
  674. ; in bx, the pointer to the line in ax.
  675. putcirc    proc    near
  676.     push    si
  677.     push    di
  678.     push    cx
  679.     push    dx
  680.     mov    di,[bx].pp        ; pick up buffer ptr
  681.     add    di,2*swidth        ; increment to next avail slot
  682.     cmp    di,[bx].bend        ; past end?
  683.     jb    putci1            ; no, leave alone
  684.     mov    di,[bx].orig        ; else start at beginning
  685. putci1:    mov    [bx].pp,di        ; update ptr
  686.     mov    si,ax            ; this is source
  687.     mov    cx,swidth
  688.     rep    movsw            ; copy into buffer
  689.     cmp    [bx].lcnt,npgs*slen    ; can we increment it?
  690.     jae    putci2            ; no, keep going
  691.     inc    [bx].lcnt        ; else count this line
  692. putci2:    pop    dx
  693.     pop    cx
  694.     pop    di
  695.     pop    si            ; restore registers
  696.     ret
  697. putcirc    endp
  698.  
  699. ; get a line from the circular buffer, removing it from the buffer.
  700. ; returns with carry on if the buffer is empty.
  701. ; pass the buffer structure in bx, the buffer to copy the line into
  702. ; in ax.
  703. getcirc    proc    near
  704.     push    si
  705.     push    di
  706.     push    cx
  707.     push    dx
  708.     cmp    [bx].lcnt,0        ; any lines in buffer?
  709.     jne    getci1            ; yes, ok to take one out.
  710.     stc                ; else set carry
  711.     jmp    short getcir3        ; and return
  712. getci1:    mov    si,[bx].pp        ; this is source
  713.     mov    di,ax            ; this is dest
  714.     mov    cx,swidth        ; # of chars to copy
  715.     rep    movsw
  716.     mov    si,[bx].pp        ; get ptr again
  717.     sub    si,2*swidth        ; move back
  718.     cmp    si,[bx].orig        ; compare to origin
  719.     jae    getcir2            ; still in range, continue
  720.     mov    si,[bx].bend        ; else use end of buffer
  721.     sub    si,2*swidth-1        ; minus length of a piece
  722. getcir2:mov    [bx].pp,si        ; update ptr
  723.     dec    [bx].lcnt        ; decrement # of lines in buffer
  724.     clc                ; make sure no carry
  725. getcir3:pop    dx
  726.     pop    cx
  727.     pop    di
  728.     pop    si
  729.     ret
  730. getcirc    endp
  731.  
  732. ; call before scrolling to save top line...
  733. scrprep    proc    near
  734.     push    ds
  735.     mov    si,0            ; offset of top line
  736.     mov    cx,swidth        ; length of line
  737.     mov    di,offset tlbuf        ; place to put line temporarily
  738.     call    scrseg
  739.     push    ax
  740.     call    scrwait
  741.     pop    ds
  742.     rep    movsw            ; copy the line
  743.     pop    ds            ; restore this
  744.     mov    ax,offset tlbuf
  745.     mov    bx,offset twnd        ; this is where it goes
  746.     call    putcirc            ; put into buffer
  747.     ret                ; and return
  748. scrprep    endp
  749.  
  750.  
  751. ; put the character in al to the screen
  752. outtty    proc    near
  753.     test    flags,capt        ; capturing output?
  754.     jz    outnoc            ; no, forget this part
  755.     push    ax            ; save char
  756.     call    captrtn            ; give it captured character
  757.     pop    ax            ; restore character and keep going
  758.  
  759. outnoc:    test    flags1,prtscr        ; should we be printing?
  760.     jz    outnop            ; no, keep going
  761.     push    ax
  762.     mov    ah,print_out
  763.     mov    dl,al            ; put character here for dos...
  764.     int    dos
  765.     pop    ax
  766.  
  767. outnop:    test    flags,emheath        ; emulating heath?
  768.     jnz    outnop1            ; yup, go do something smart
  769.     mov    dl,al
  770.     mov    ah,pbout
  771.     int    dos            ; else let dos print char
  772.     ret                ; and return
  773.  
  774. outnop1:mov    dx,cursor        ; these may need cursor...
  775.     jmp    ttstate            ; jump according to current state
  776.  
  777. outtt0:
  778.     cmp    al,32            ; special character?
  779.     jb    outtt1            ; yes, handle specially...
  780.  
  781.     cmp    insmod,0        ; in insert mode?
  782.     je    outnrm            ; no, output normal
  783.     push    ax            ; save character
  784.     call    inschr            ; insert a character
  785.     pop    ax
  786. outnrm:    xor    bh,bh            ; current page
  787.     mov    cx,1            ; only one char
  788.     mov    bl,curattr        ; with current attribute
  789.     mov    ah,9
  790.     int    screen            ; put onto screen
  791.     mov    dx,cursor        ; get cursor pos
  792. currt:    inc    dl            ; bump col
  793.     cmp    dl,crt_cols        ; see if in range
  794.     jb    setcur            ; in range, go set cursor
  795.     test    flags1,lnwrap        ; in wrap mode?
  796.     jz    outign            ; no, just return w/out updating cursor
  797. wrap:    xor    dl,dl
  798.     inc    dh            ; handle wrap
  799. setcur:    cmp    dh,crt_lins
  800.     jb    setc1            ; not off end, keep going
  801.     push    dx            ; save row/col
  802.     call    scrprep            ; save top line in window buf
  803.     mov    ax,0601h        ; scroll up one line
  804.     xor    cx,cx            ; from 0,0
  805.     mov    dx,low_rgt        ; to 24,80
  806.     mov    bh,7            ; nice attribute
  807.     int    screen            ; do the scroll
  808.     pop    dx
  809.     mov    dh,crt_lins        ; go to bottom line again...
  810.     dec    dh
  811. setc1:    xor    bh,bh            ; page is 0
  812.     mov    cursor,dx        ; save cursor pos
  813.     mov    ah,2
  814.     int    screen            ; set cursor
  815. outign:    ret                ; and return
  816. ; special character (in al)
  817. outtt1:    mov    di,offset spctab    ; special char table
  818.     mov    cx,lspctab        ; length of tbl
  819.     repne    scasb            ; look for char in tbl
  820.     jz    outtt2            ; found, go do something with it
  821.     test    flags,trnctl        ; are we allowed to print carets?
  822.     jz    outign            ; no, just ignore it.
  823.     push    ax            ; save char
  824.     mov    al,'^'
  825.     call    outtty            ; print caret
  826.     pop    ax
  827.     add    al,'A'-1        ; make printable
  828.     jmp    outtty            ; print, then return
  829.  
  830. outtt2:    mov    dx,cursor        ; might need cursor pos
  831.     sub    di,offset spctab+1    ; get index of char
  832.     shl    di,1            ; double for word offset
  833.     jmp    spcjmp[di]        ; and go handle
  834.  
  835. ; special char routines.  cursor is in dx, char in al
  836.  
  837. outlf:    inc    dh            ; bump row
  838.     jmp    setcur
  839.  
  840. outcr:    xor    dl,dl            ; set col to 0
  841.     jmp    setcur
  842.  
  843. outbs:    or    dl,dl
  844.     jle    setcur            ; col 0, can't back up
  845.     dec    dl            ; back up col
  846.     jmp    setcur            ; and use if reasonable
  847.  
  848. outtab:    mov    dl,byte ptr cursor    ; get initial column
  849.     add    dl,8            ; tab is at most 8 columns
  850.     and    dl,not 111b        ; round down to a multiple of 8
  851.     cmp    dl,crt_cols        ; out of range?
  852.     jb    setcur            ; no, go set it
  853.     test    flags1,lnwrap        ; in wrap mode?
  854.     jnz    outta1            ; yes, wrap to next line
  855.     mov    dl,byte ptr low_rgt    ; else just move to right margin
  856.     jmp    setcur
  857. outta1:    jmp    wrap
  858.     
  859. ; stolen from bios
  860. outbel:    mov    al,10110110b        ; timer initialization
  861.     out    timer+3,al
  862.     mov    ax,beldiv        ; bel divisor
  863.     out    timer+2,al
  864.     mov    al,ah
  865.     out    timer+2,al        ; output divisor
  866.     in    al,bel_prt
  867.     mov    ah,al            ; remember original value
  868.     or    al,3            ; turn speaker on
  869.     out    bel_prt,al
  870.     mov    cx,8888h
  871. outbe1:    loop    outbe1            ; wait a while
  872.     mov    al,ah
  873.     out    bel_prt,al        ; turn bell off
  874.     ret                ; and return
  875.  
  876. outesc:    mov    ttstate,offset escseq    ; expect escape sequence.
  877.     ret                ; and return
  878.  
  879. ; escape-char handling routines
  880. escseq:    mov    ttstate,offset outtt0    ; put state back to normal
  881.     mov    di,offset esctab    ; escape char tbl
  882.     mov    cx,lesctab        ; length of tbl
  883.     repne    scasb            ; look for it in tbl
  884.     jz    escsq1            ; found, go use it
  885.     jmp    outtty            ; not there, just print it
  886. escsq1:    sub    di,offset esctab+1    ; get offset into tbl
  887.     shl    di,1            ; convert to word offset
  888.     jmp    escjmp[di]        ; and go dispatch on it
  889.  
  890. ; escape dispatch routines
  891. revind:    cmp    dh,0
  892.     jle    revin1
  893.     dec    dh            ; back up a row
  894.     jmp    setcur            ; and go set cursor
  895. revin1:    push    dx            ; save cursor pos
  896.     mov    ax,701h            ; scroll down one line
  897.     xor    cx,cx            ; from top
  898.     mov    dx,low_rgt        ; to bottom
  899.     mov    bh,curattr
  900.     int    screen            ; scroll it down
  901.     pop    dx            ; restore cursor.
  902.     mov    dh,0            ; set row back to 0
  903.     jmp    setcur
  904.  
  905. curup:    cmp    dh,0            ; w/in range?
  906.     jle    curu1            ; no, skip this
  907.     dec    dh            ; else back up
  908. curu1:    jmp    setcur            ; and go set position
  909.  
  910. curdwn:    inc    dh
  911.     jmp    setcur            ; increment row (setcur can scroll!)
  912.  
  913. ; currt is above
  914.  
  915. clrscr:    call    curhom            ; go home cursor
  916.     jmp    clreow            ; then clear to end of window
  917.  
  918. curhom:    xor    dx,dx            ; move to 0,0
  919.     jmp    setcur
  920.  
  921. clreow:    cmp    dl,0            ; at beginning of line?
  922.     jz    clrw1            ; yes, skip this part...
  923.     push    dx            ; remember cursor pos
  924.     call    clreol            ; clear to end of this line
  925.     pop    dx
  926.     inc    dh            ; bump row
  927.     xor    dl,dl            ; start from col 0
  928. clrw1:    cmp    dh,crt_lins        ; last line on screen
  929.     jnb    clrw2            ; if not in range, forget it
  930.     mov    ax,700h            ; clear whole window
  931.     mov    cx,dx            ; this is beginning
  932.     mov    dx,low_rgt
  933. ;    mov    dx,174fh        ; this is lower right corner
  934.     mov    bh,curattr        ; default attribute
  935.     int    screen            ; go clear it
  936. clrw2:    ret                ; and return
  937.  
  938. clreol:    push    es
  939.     mov    cl,crt_cols        ; last col + 1
  940.     sub    cl,dl            ; this is # of chars to move
  941.     xor    ch,ch
  942.     jcxz    clrl1
  943.     call    scrloc            ; compute screen location (to ax)
  944.     mov    di,ax
  945.     call    scrseg
  946.     mov    es,ax            ; address screen segment
  947.     call    scrwait            ; wait for retrace
  948.     mov    ah,curattr        ; current attribute
  949.     mov    al,' '            ; fill char
  950.     rep    stosw            ; fill line with spaces
  951. clrl1:    pop    es
  952.     ret                ; and return
  953.  
  954. inslin:    mov    al,1            ; scroll one line
  955. ; alternate entry if inserting more then one line
  956. inslin1:mov    ch,dh            ; start at current row
  957.     xor    cl,cl            ; column 0
  958.     mov    dx,low_rgt
  959.     mov    ah,7h            ; scroll down.
  960.     mov    bh,curattr        ; attribute
  961.     cmp    ch,dh            ; moving last line down?
  962.     jne    insli2            ; no, keep going
  963.     mov    al,0            ; yes, just clear it
  964. insli2:    int    screen
  965.     ret
  966.  
  967. dellin:    mov    al,1            ; scroll 1 line
  968. ; alternate entry if deleting more than one line
  969. dellin1:mov    ch,dh            ; start at current row
  970.     xor    cl,cl            ; column 0
  971.     mov    dx,low_rgt
  972. ;    mov    dx,174fh        ; to bottom of screen
  973.     mov    ah,6h            ; scroll up.
  974.     mov    bh,curattr        ; attribute
  975.     cmp    ch,dh            ; deleting last line?
  976.     jne    delli2            ; no, go on
  977.     mov    al,0            ; yes, just blank it
  978. delli2:    int    screen
  979.     ret
  980.  
  981. delchr:    push    ds
  982.     push    es
  983.     pushf            ; these may get changed...
  984.     mov    cl,crt_cols
  985.     dec    cl
  986.     sub    cl,dl        ; from what we're fiddling)
  987.     xor    ch,ch
  988.     jcxz    delch1        ; none to move, forget it
  989.     call    scrloc        ; compute location
  990.     mov    di,ax
  991.     mov    si,ax
  992.     add    si,2        ; source is next position over
  993.     call    scrseg        ; pick up screen segment
  994.     push    ax        ; put screen segment onto stack
  995.     mov    es,ax        ; and in destination segment
  996.     call    scrwait        ; wait for retrace
  997.     pop    ds        ; address screen segment
  998.     rep    movsw        ; delete it
  999.     mov    byte ptr [di],' ' ; kill char at end of line
  1000. delch1:    popf
  1001.     pop    es
  1002.     pop    ds
  1003.     ret
  1004.  
  1005. inschr:    push    ds
  1006.     push    es        ; save these as well
  1007.     pushf            ; might as well save flags...
  1008.     mov    dx,cursor    ; this is place to do it
  1009.     mov    cl,crt_cols
  1010.     dec    cl
  1011. ;    mov    cl,79        ; this is last col to move, +1 for length
  1012.     sub    cl,dl        ; compute distance to end
  1013.     xor    ch,ch        ; clear top half of offset
  1014.     jcxz    insch1        ; nothing to move...
  1015.     mov    dl,crt_cols
  1016.     sub    dl,2        ; last col to move
  1017. ;    mov    dl,78        ; this is address of last col to move
  1018.     call    scrloc        ; compute pos
  1019.     mov    si,ax
  1020.     mov    di,ax
  1021.     add    di,2        ; destination is one byte over...
  1022.     std            ; remember to move us backwards
  1023.     call    scrseg        ; find screen segment
  1024.     mov    es,ax
  1025.     push    ax        ; save screen seg on stack
  1026.     call    scrwait        ; wait until save to write
  1027.     pop    ds        ; address screen segment
  1028.     rep    movsw        ; move each char and attribute
  1029. insch1:    popf
  1030.     pop    es
  1031.     pop    ds
  1032.     ret            ; and return
  1033.  
  1034. noins:    mov    insmod,0        ; turn off insert mode
  1035.     ret                ; and return
  1036.  
  1037. movcur:    mov    wcoord,2        ; want two coordinates...
  1038.     mov    ttstate,offset getcoord
  1039.     ret                ; and return
  1040.  
  1041. vtident: mov    si,offset vtidstr
  1042.     mov    cx,lvtidst
  1043. vtid1:    lodsb                ; get a byte from the string
  1044.     push    si            ; have to save from outprt
  1045.     push    cx
  1046.     call    outprt            ; send to serial port
  1047.     pop    cx
  1048.     pop    si
  1049.     loop    vtid1            ; go thru all chars
  1050.     ret                ; and return
  1051.  
  1052. entins:    mov    insmod,0ffh        ; enter insert mode...
  1053.     ret                ; and return
  1054.  
  1055. doansi:    mov    ansarg,0        ; ansi argument is 0 (default)
  1056.     mov    ttstate,offset getaarg    ; state is get ansi argument
  1057.     ret
  1058.  
  1059. getaarg:cmp    al,'0'
  1060.     jb    getaa1            ; in range for digit?
  1061.     cmp    al,'9'
  1062.     ja    getaa1
  1063.     sub    al,'0'            ; convert to binary
  1064.     mov    dl,al            ; tuck away
  1065.     mov    al,ansarg
  1066.     mov    dh,10
  1067.     mul    dh            ; shift sum
  1068.     add    al,dl            ; add in this digit (what about ovfl?)
  1069.     mov    ansarg,al
  1070.     ret                ; and return
  1071.  
  1072. getaa1:    cmp    al,'?'            ; the dreaded question mark?
  1073.     jne    getaa2
  1074.     mov    ttstate,offset ignn    ; we ignore these...
  1075.     mov    igncnt,2        ; this is how many chars come after him
  1076.     ret
  1077.  
  1078. getaa2:    mov    ttstate,offset outtt0    ; reset state
  1079.     mov    dx,cursor        ; this needs cursor position
  1080.     mov    bl,ansarg
  1081.     xchg    al,bl            ; put argument in nice place
  1082.     cmp    bl,'L'            ; insert line?
  1083.     jne    getaa3
  1084.     jmp    inslin1            ; and go do it
  1085.  
  1086. getaa3:    cmp    bl,'M'            ; maybe delete line?
  1087.     jne    getaa4
  1088.     jmp    dellin1
  1089.  
  1090. getaa4:    ret                ; ignore.
  1091.  
  1092. invvid:    mov    curattr,70h        ; attribute for inverse video
  1093.     ret
  1094.  
  1095. nrmvid:    mov    curattr,07h        ; attribute for normal video
  1096.     ret
  1097.  
  1098. dowrap:    or    flags1,lnwrap        ; turn on wrap mode
  1099.     ret                ; and return
  1100.  
  1101. nowrap:    and    flags1,not lnwrap    ; turn off wrap mode
  1102.     ret                ; and return
  1103.  
  1104. ; get a coordinate.
  1105. getcoord:
  1106.     sub    al,32            ; coordinates offset by 32
  1107.     mov    si,wcoord
  1108.     dec    si
  1109.     mov    byte ptr coord[si],al    ; fill in appropriate coordinate
  1110.     mov    wcoord,si        ; update flag
  1111.     jnz    getco1            ; more needed, can't do anything yet
  1112.     mov    ttstate,offset outtt0    ; reset state
  1113.     mov    dx,coord        ; get coordinates
  1114.     jmp    setcur            ; and go jump there
  1115. getco1:    ret
  1116.  
  1117. ; ignore following igncnt characters
  1118. ignn:    dec    igncnt            ; decrement count
  1119.     jnz    ignn1
  1120.     mov    ttstate,offset outtt0    ; put state back to normal if done
  1121. ignn1:    ret
  1122.  
  1123. ; save cursor
  1124. savecur:
  1125.     mov    oldcur,dx
  1126.     ret
  1127.  
  1128. ; restore cursor
  1129. restcur:
  1130.     mov    dx,oldcur
  1131.     jmp    setcur
  1132.     
  1133. outtty    endp
  1134.  
  1135. ; computes screen location to ax, given row and col in dx.
  1136. ; trashes ax,bx
  1137. scrloc    proc    near
  1138.     mov    al,dh        ; get row
  1139.     mov    bl,crt_cols    ;** row size
  1140.     mul    bl        ; multiply by row size
  1141.     xor    dh,dh        ; clear col
  1142.     add    ax,dx        ; this is current position
  1143.     sal    ax,1        ; double for attributes
  1144.     ret
  1145. scrloc    endp
  1146.  
  1147. ; puts current screen segment in ax
  1148. scrseg    proc    near
  1149.     mov    ax,0b000h        ; assume bw for now
  1150.     cmp    crt_mode,7        ; 7 is bw (***)
  1151.     je    scrse1
  1152.     mov    ax,0b800h        ; color card
  1153. scrse1:    ret
  1154. scrseg    endp
  1155.  
  1156. ; wait for retrace so can write to screen memory
  1157. scrwait    proc    near
  1158.     cmp    crt_mode,7        ; bw mode?
  1159.     je    scrwa3            ; yes, no waiting
  1160.     push    dx
  1161.     mov    dx,crt_status
  1162. scrwa1:    in    al,dx
  1163.     test    al,disp_enb        ; display enable?
  1164.     jnz    scrwa1            ; yes, keep waiting
  1165. scrwa2:    in    al,dx
  1166.     test    al,disp_enb        ; now wait for it to go off
  1167.     jz    scrwa2            ; so can have whole cycle
  1168.     pop    dx
  1169. scrwa3:    ret                ; that was easy...
  1170. scrwait    endp
  1171. code    ends
  1172.  
  1173. if1
  1174.     %out [End of pass 1]
  1175. else
  1176.     %out [End of assembly]
  1177. endif
  1178.  
  1179.     end
  1180.  
  1181.